package com.jzy.weblog.jwt.config;

import com.jzy.weblog.jwt.filter.JwtAuthenticationFilter;
import com.jzy.weblog.jwt.handler.RestAuthenticationFailureHandler;
import com.jzy.weblog.jwt.handler.RestAuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

//配置 JWT（JSON Web Token）的身份验证机制
//继承了 Spring Security 的 SecurityConfigurerAdapter 类，用于在 Spring Security 配置中添加自定义的认证过滤器和提供者

@Configuration
public class JwtAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

    @Autowired
    private RestAuthenticationSuccessHandler restAuthenticationSuccessHandler;

    @Autowired
    private RestAuthenticationFailureHandler restAuthenticationFailureHandler;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserDetailsService userDetailsService;

    //重写 configure() 方法，我们将之前写好过滤器、认证成功、失败处理器，以及加密算法整合到了 httpSecurity 中
    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        // 自定义的用于 JWT 身份验证的过滤器
        JwtAuthenticationFilter filter = new JwtAuthenticationFilter();
        filter.setAuthenticationManager(httpSecurity.getSharedObject(AuthenticationManager.class));

        // 设置登录认证对应的处理类（成功处理、失败处理）
        filter.setAuthenticationSuccessHandler(restAuthenticationSuccessHandler);
        filter.setAuthenticationFailureHandler(restAuthenticationFailureHandler);

        // 直接使用 DaoAuthenticationProvider, 它是 Spring Security 提供的默认的身份验证提供者之一
        // 会调用你实现的 UserDetailsService 的 loadUserByUsername() 方法
        // 使用 PasswordEncoder.matches() 比对密码是否匹配
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        // 设置 userDetailService，用于获取用户的详细信息
        provider.setUserDetailsService(userDetailsService);
        // 设置加密算法
        provider.setPasswordEncoder(passwordEncoder);
        httpSecurity.authenticationProvider(provider);
        // 将这个过滤器添加到 UsernamePasswordAuthenticationFilter 之前执行
        // 替代默认的表单登录逻辑
        httpSecurity.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
    }
}

//POST /login
//   ↓
//JwtAuthenticationFilter
//   ↓
//封装用户名密码 → UsernamePasswordAuthenticationToken
//   ↓
//AuthenticationManager
//   ↓
//DaoAuthenticationProvider
//   ↓
//UserDetailsService → 获取用户信息
//PasswordEncoder → 校验密码
//   ↓
//登录成功？→ SuccessHandler → 生成 JWT Token
//否→ FailureHandler → 返回错误信息
